<template>
  <div v-show="showWrapper" class="chat-wrapper">
    <Transition name="zoom" @after-leave="afterLeave">
      <div v-if="rendered" v-show="visible" v-chat-drag :class="['chat-client', 'chat-window', { fullscreen }]">
        <!--侧栏-->
        <div class="chat-sidebar">
          <!--搜索框-->
          <ChatSearchBar v-model="query" @confirm="onConfirm" />
          <!--会话列表-->
          <ChatThreads ref="chatThreads" v-model="currentSession" :query="query" />
        </div>
        <!--右侧聊天区域-->
        <div class="main">
          <!--顶部工具条-->
          <ChatToolbar
            :fullscreen.sync="fullscreen"
            :session="currentSession"
            closeable
            @tab-change="onTabChange"
            @close="hide" />
          <!--聊天-->
          <div v-show="tab === 'chat'" class="chat-panel">
            <div class="chat-panel-inner">
              <!--聊天区-->
              <div v-if="currentSession.id" class="chat-area">
                <SplitPane v-model="offset" mode="vertical" min="250px" max="250px">
                  <template #top>
                    <!--消息区-->
                    <ChatMessageBox :key="currentSession.id" ref="chatMessageBox" :session="currentSession" />
                  </template>
                  <template #bottom>
                    <!--输入区-->
                    <ChatRichTextEditAreaNew
                      ref="editor"
                      :disabled="currentSession.status === 0 || isBan"
                      :disabled-tips="isBan ? '你已被禁言' : ''"
                      :session="currentSession"
                      closeable
                      @send-success="onSendSuccess"
                      @close="hide" />
                  </template>
                </SplitPane>
              </div>
              <EmptyView
                v-show="!currentSession.id"
                show-icon
                icon-size="2.5em"
                icon="el-icon-chat-dot-round"
                font-size="26px"
                empty-tips="即时聊天" />
              <!--群成员-->
              <div
                v-show="currentSession.type === 'group' && currentSession.status === 1"
                class="chat-group-users-wrapper">
                <ChatGroupUsers ref="chatGroupUsers" v-model="currentGroupMember" :session="currentSession" />
              </div>
            </div>
          </div>
          <!--文件-->
          <div v-if="tab === 'file'" class="chat-file-panel">
            <XFileExplorerLite
              :key="currentSession.id"
              :delete-api="deleteFile"
              :update-api="renameFile"
              :menu="menu"
              memory
              :upload-params="bizInfo"
              :buttons="[]"
              :fetch-api="getFiles" />
          </div>
        </div>
      </div>
    </Transition>
    <!--遮罩层-->
    <div v-show="visible" class="chat-mask"></div>
  </div>
</template>

<script>
  import chatDrag from '@/vue/directives/chat-drag'
  import ChatMessageBox from './ChatMessageBox'
  import ChatSearchBar from './ChatSearchBar'
  import ChatThreads from './ChatThreads'
  import ChatToolbar from './ChatToolbar.vue'
  import ChatGroupUsers from './ChatGroupUsers.vue'
  import ChatRichTextEditAreaNew from './ChatRichTextEditAreaNew.vue'
  import XFileExplorerLite from '@/components/x-file-explorer-lite/XFileExplorerLite.vue'
  import message from '@/vue/mixin/message'
  import { mapMutations, mapState } from 'vuex'
  import { deleteFile, getFiles, renameFile } from '@/api/file'
  import { newThread } from '@/components/im/api/thread'

  export default {
    name: 'ChatWindow',
    components: {
      XFileExplorerLite,
      ChatGroupUsers,
      ChatToolbar,
      ChatSearchBar,
      ChatThreads,
      ChatMessageBox,
      ChatRichTextEditAreaNew
    },
    directives: {
      chatDrag
    },
    mixins: [message],
    provide() {
      return {
        chatClient: this
      }
    },
    message: {
      chat() {
        if (!this.$refs.chatThreads) {
          this.adjustUnreadCount(1)
        }
        this.playSound()
      }
    },
    props: {
      visible: {
        type: Boolean,
        default: false
      },
      closeOnPressEscape: {
        type: Boolean,
        default: true
      },
      closeOnHashChange: {
        type: Boolean,
        default: true
      }
    },
    data() {
      return {
        currentSession: {},
        currentGroupMember: null,
        query: '',
        offset: 0.6,
        rendered: false,
        showWrapper: false,
        fullscreen: false,
        tab: 'chat'
      }
    },
    computed: {
      ...mapState('user', { userId: state => state.sysUser.userId }),
      bizInfo() {
        return { bizId: this.currentSession.thread?.id, bizName: 'IM' }
      },
      isBan() {
        return this.currentSession.type === 'group' && this.currentGroupMember?.status === 1
      }
    },
    watch: {
      'currentSession.type'(newVal) {
        if (newVal === 'p2p') {
          this.currentGroupMember = null
        }
      },
      visible: {
        immediate: true,
        handler(val) {
          if (val) {
            this.showWrapper = true
          }
          if (val && !this.rendered) {
            this.rendered = true
          }
        }
      }
    },
    mounted() {
      this.initAudio()
      if (this.closeOnPressEscape) {
        window.addEventListener('keydown', this.onKeyDown)
      }
      if (this.closeOnHashChange) {
        window.addEventListener('hashchange', this.hide)
      }
      this.$once('hook:beforeDestroy', () => {
        this.hide()
        if (this.closeOnPressEscape) {
          window.removeEventListener('keydown', this.onKeyDown)
        }
        if (this.closeOnHashChange) {
          window.removeEventListener('hashchange', this.hide)
        }
      })
      document.body.append(this.$el)
    },
    destroyed() {
      this.$el.remove()
    },
    methods: {
      ...mapMutations('im', ['adjustUnreadCount']),
      menu(currentRow) {
        const menu = []
        if (!currentRow) {
          return menu
        }
        menu.push({
          text: '查看',
          action: 'view',
          icon: 'el-icon-view',
          type: ['file']
        })

        if (this.userId === currentRow.creator.userId || this.currentGroupMember?.role > 0) {
          menu.push({
            text: '重命名',
            action: 'rename',
            icon: 'el-icon-edit-outline',
            type: ['directory', 'file']
          })
          menu.push({
            text: '删除',
            action: 'del',
            icon: 'el-icon-circle-close',
            type: ['directory', 'file']
          })
        }
        menu.push({
          text: '下载',
          action: 'download',
          icon: 'el-icon-download',
          type: ['file']
        })
        return menu
      },
      renameFile(fileId, file) {
        return renameFile(fileId, file)
      },
      deleteFile(ids) {
        return deleteFile(ids)
      },
      getFiles(directory, page, searchText) {
        const { page: current, size } = page
        return getFiles({
          current,
          size,
          descs: ['createdAt'],
          example: {
            ...this.bizInfo,
            'parent.id': directory,
            filename: searchText
          }
        })
      },
      playSound() {
        this.initAudio()
        this.audio.play()
      },
      initAudio() {
        if (!this.audio) {
          this.audio = document.createElement('audio')
          this.audio.setAttribute('src', require('@/assets/media/wechat.mp3'))
          this.$el.appendChild(this.audio)
        }
      },
      onTabChange(tab) {
        this.tab = tab
      },
      onKeyDown(event) {
        if (event.keyCode === 27) {
          this.hide()
        }
      },
      hide() {
        this.$emit('update:visible', false)
      },
      async onSendSuccess(message) {
        await this.$refs.chatMessageBox.append(message)
        await this.$refs.chatMessageBox.scrollToBottomOnImageLoaded()
        await this.$refs.chatThreads.updateLatestMessage(message)
      },
      async onConfirm(users) {
        let res
        if (users.length > 1) {
          const result = await this.$prompt('请输入群聊名称', {
            inputValidator(val) {
              if (!val) {
                return '请输入群聊名称'
              } else if (val.trim().length < 4) {
                return '群聊名称最少需要输入4个字符'
              } else {
                return true
              }
            }
          })
          res = await newThread({ userIds: users.map(value => value.id), type: 'group', name: result.value })
        } else {
          res = await newThread({ userIds: [users[0].id], type: 'p2p' })
        }
        this.$refs.chatThreads.setActiveThreadId(res.data.data.id)
      },
      afterLeave() {
        this.showWrapper = false
      }
    }
  }
</script>

<style lang="scss">
  .chat-client {
    z-index: 3;
    height: 100%;
    overflow: hidden;
    border-radius: 4px;

    &.chat-window {
      position: relative;
      z-index: 1;
      width: 1000px;
      height: 560px;

      &.fullscreen {
        top: 0 !important;
        left: 0 !important;
        width: 100%;
        height: 100%;
      }
    }

    .chat-sidebar,
    .main {
      height: 100%;
    }

    .chat-sidebar {
      float: left;
      width: 290px;
      color: black;
      background-color: #fcfcfc;
      border: 1px solid #e0e0e0;
      border-right: none;
    }

    .main {
      position: relative;
      display: flex;
      flex-direction: column;
      height: 100%;
      overflow: visible;
      background-color: #f7f7f7;
      border: 1px solid #e0e0e0;
    }

    .chat-panel {
      position: relative;
      display: flex;
      flex: 1 1 auto;
    }

    .chat-panel-inner {
      position: absolute;
      top: 0;
      bottom: 0;
      display: flex;
      width: 100%;
    }

    .chat-area {
      display: flex;
      flex: 1 1 auto;
      flex-direction: column;
      height: 100%;
      overflow: hidden;
    }

    .chat-file-panel {
      display: flex;
      flex: 1 1 auto;
      flex-direction: column;
      height: 100%;
    }

    .chat-group-users-wrapper {
      @include flex-not-shrink;
      position: relative;
      display: flex;
      flex-direction: column;
      width: 160px;
      background-color: #fff;
      border-left: 1px solid #eee;
    }
  }

  .chat-wrapper {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100vw;
    height: 100vh;
    overflow: auto;
  }

  .chat-mask {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background: #000;
    opacity: 0.5;
  }

  .chat-message-content {
    @include break-word;

    * {
      word-break: break-word;
    }

    p {
      // height: 24px;
      line-height: 24px;
      text-indent: 0 !important;
    }

    .chat-image {
      max-width: 200px;
      cursor: pointer;
    }

    img {
      max-width: 100%;
      height: unset;
      vertical-align: middle;
    }

    img[data-w-e],
    img[data-emotion] {
      width: 20px !important;
      height: 20px !important;
      margin: 0 2px;
      vertical-align: bottom;
      cursor: default;

      &:hover {
        box-shadow: none;
      }
    }

    img[data-emotion] {
      width: 24px !important;
      height: 24px !important;
    }
  }

  .chat-link {
    color: var(--color-primary) !important;
    text-decoration: underline;
  }

  .file-item {
    display: flex;
    align-items: center;
    width: 382px;
    max-width: 100%;
    padding-top: 6px;
    padding-bottom: 6px;
    background-color: #fff;
    border: 1px solid #e5e5e5;
    border-radius: 4px;
  }

  .file-item-wrapper {
    display: flex;
    flex: 5;
    flex-direction: column;
    justify-content: center;
  }

  .file-item-icon {
    flex: 1.5;
    height: 60px;
    line-height: 70px;
    text-align: center;
    background-repeat: no-repeat;
    background-position: center;
    background-size: contain;
  }

  .file-item-name {
    width: 100%;
    padding-right: 10px;
    font-size: 1.2em;
    line-height: 1.5;
    word-break: break-word;

    @include ellipsis(2);
    @include clickable;
  }

  .file-item-size {
    flex: 1 1 auto;
    color: #808080;
    font-size: 0.9em;
  }

  .file-item-download {
    color: var(--color-primary);

    &:hover {
      text-decoration: underline;
    }
  }

  .file-item-footer {
    display: flex;
    margin-top: 4px;
    padding-right: 10px;
    font-size: 13px;
  }

  .w-e-text-container [data-slate-editor] blockquote.reply-message-blockquote,
  .reply-message-blockquote {
    display: block;
    padding: 4px;
    color: #888;
    font-size: 14px;
    background-color: #f5f2f0;
    border: 1px solid #eee;
    border-left: 4px solid var(--color-primary);
    border-radius: 4px;

    .reply-message-user-name {
      margin-right: 10px;
    }

    .file-item {
      padding: 4px;
    }

    .file-item-name {
      font-size: 12px;
    }

    img {
      max-height: 50px;
    }

    p {
      @include ellipsis-line;
      margin: 0;
      overflow: hidden;
      white-space: nowrap;
      word-break: keep-all;

      &:last-child {
        margin: 0;
      }
    }
  }
</style>
